#include <iostream>
#include "ViewControl.h"
#include "../common/LightInputDriver.h"
#include "Controller.h"
#include "Recognizer.h"

// Modules
Ptr< Controller > glbpController;
Ptr< LightInputDriver > glbpLightInputDriver;
Ptr< GlControl > glbpViewControl;
Ptr< Recognizer > glbpRecognizer;

// Global Objects
float xPoint = -1.0f, yPoint = -1.0f;
Ptr< list< Ptr< Object > > > glbpObjList;
Ptr< BattleStatus > glbpBattleStatus;
Ptr< queue< Request > > glbpReqQueue;
Ptr< Terrain > glbpTerrain;

bool global_init ();

bool module_init ();

void start_multi_thread ();

DWORD WINAPI start_light_thread (LPVOID lpParam);
DWORD WINAPI start_control_thread (LPVOID lpParam);
DWORD WINAPI start_speech_thread (LPVOID lpParam);


int main(int argc, char** argv)
{
  // Initialize openGL environment
  glutInit(&argc, argv);

  if (!global_init ())
    return -1;
  Ptr< ObjectProperty > pArmy = new ObjectProperty (5.0f, true, true, true,
    0.3f, // basic attack power
    3.0f, // basic attack range
    0.1f, // basic missing chance
    0.1f, // basic defense
    0.1f, // basic avoiding chance
    0.0f  // basic speed
    );

  Ptr< Object > test = new Object (ARMY, glbpBattleStatus->cur_player (),
    pArmy, glbpTerrain, 18.0f, 18.0f);

  test->set_target( 50 , 50);

  glbpObjList->push_back (test);

  if (!module_init ())
    return -1;

  start_multi_thread ();
  glenv_run (glbpViewControl);

  return 0;
}


bool global_init ()
{

  glbpObjList = new list< Ptr< Object > > ();
  glbpReqQueue = new queue< Request > ();
  glbpBattleStatus = new BattleStatus ();
  glbpTerrain = new Terrain (TERRAIN_FILE);

  return true;

}



bool module_init ()
{

  cout << "Start initialize modules..." << endl;

  // Initialize Light Input Driver
  cout << "Initializing Module: LightInputDriver..." << endl;
  glbpLightInputDriver =
    new LightInputDriver (&xPoint, &yPoint, glbpReqQueue);

  // Initialize Speech Recognize
  cout << "Initializing Module: Recognizer..." << endl;
  glbpRecognizer = new Recognizer (glbpReqQueue, &xPoint, &yPoint);

  // Initialize Controller
  cout << "Initializing Module: Controller..." << endl;
  glbpController = new Controller (glbpObjList, glbpBattleStatus,
    glbpReqQueue, glbpTerrain);

  // Initialize View Control
  cout << "Initializing Module: ViewControl..." << endl;
  glenv_create_window (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH, "PRP", true);
  glbpViewControl = new ViewControl (glbpTerrain, 
    glbpBattleStatus, glbpObjList);

  return true;

}


void start_multi_thread ()
{
  HANDLE threadHandle[4];

  threadHandle[0] = CreateThread (NULL, 0,
    start_control_thread, NULL, 0, NULL);
  threadHandle[1] = CreateThread (NULL, 0,
    start_light_thread, NULL, 0, NULL);
  threadHandle[2] = CreateThread (NULL, 0,
    start_speech_thread, NULL, 0, NULL);

}



DWORD WINAPI start_light_thread (LPVOID lpParam)
{
  glbpLightInputDriver->run ();
  return 0;
}

DWORD WINAPI start_control_thread (LPVOID lpParam)
{
  glbpController->run ();
  return 0;
}

DWORD WINAPI start_speech_thread (LPVOID lpParam)
{
  glbpRecognizer->startup ();
  return 0;
}